package com.okaysoft.ofb

import com.okaysoft.ofb.account.Department
import com.okaysoft.ofb.account.Role
import com.okaysoft.ofb.account.Requestmap
import com.okaysoft.ofb.account.User
import grails.converters.JSON

class SysService {
    def springSecurityService

    def departmentTreeJson(parentId) {
        def departments
        def params =  [sort: 'orderNumber',order: 'asc']
        if(!parentId) {
            departments= Department.findAllByParentIdIsNull(params)
        }else{
            departments = Department.findAllByParentId(parentId,params)
        }
        if(!departments || departments.size() ==0) {
            return []
        }
        return departments.collect {depart->
            [id:depart.id,text:depart.name,description: depart.description, parentId: depart.parentId,parentName: depart.parentName, children:departmentTreeJson(depart.id)]
        }
    }

    static def LETTERS = ('A'..'Z')
    static Integer FORMWORK_TERMINAL_L = 12
    def saveDevice(Device device,def zg=[],def px=[]){
        if (!device.save(flush: true)) {
            log.error(device.errors)
            throw new RuntimeException()
        }
        def t = Terminal.findByDevice(device)
        if(t){
             return
        }
        def formwork = device.formwork
        def dets = formwork.formworkDetails
        def cap = 0

        dets.each {det->
            def categroyId = det.category.id
            def category = (categroyId == 0?'a':'b')
            def compositions = det.formworkCompositions
            compositions.each {c->
                def number = c.number
                def quantity = c.quantity
                cap += quantity.intValue() * FORMWORK_TERMINAL_L
                for(int i=0;i<quantity;i++){
                    if(i>26){
                        break;
                    }
                    def l = LETTERS[i]
                    def zgTer = zg.find {ele->
                        "${category}${number}_${l}"=="${ele}"
                    }
                    def pxTer = px.find {ele->
                        "${category}${number}_${l}"=="${ele}"
                    }

                    for (int j=1;j<=FORMWORK_TERMINAL_L;j++) {
                        def num = "${device.id}_${category}${number}_${l}_${j}"
                       def ter = new Terminal([device:device,area:"${category}${number}",number:num,terId:"${category}${number}_${l}_${j}",
                               letter:"${l}",letterNumber:"${j}",status:Terminal.Status.WELDING_NO_JUMPER,
                               code:num])
                        if(zgTer){
                            ter.backboneWiring= Terminal.BackboneWiring.BACKBONE
                        }
                        if(pxTer) {
                            ter.backboneWiring= Terminal.BackboneWiring.WIRING
                        }
                        if(!ter.save(flush: true)){
                            log.error(ter.errors)
                        }
                    }
                }
            }
        }

        def capactity = new Capacity()
        capactity.actual=cap
        device.capacity=capactity
        device.save()
    }
    
    def removeDevice(Device dev){
        def task = Task.where {
            device == dev
        }
        task.deleteAll()
        def ts = Terminal.findAllByDevice(dev)
        ts.each {t->
            TerminalClientUser.removeAll(t)
            t.delete()
        }
       /* def ter = Terminal.where {
            device == dev
        }

        ter.deleteAll()
*/
        return dev.delete(flush:true)
    }
    
    
    def saveClientUser(def types,def clientUser) {

        if(!clientUser.save(flush: true)){
            throw new RuntimeException()
        }
        ClientUserType.executeUpdate("delete from ClientUserType where clientUser=:clientUser",[clientUser:clientUser])
        if(types instanceof String){
            def cutt = ClientUserType.Type."${types}"
            def cut = new ClientUserType()
            cut.type = cutt
            cut.clientUser = clientUser
            cut.save(flush: true)
        } else{
            types.each {t->
                def cutt = ClientUserType.Type."${t}"
                def cut = new ClientUserType()
                cut.type = cutt
                cut.clientUser = clientUser
                cut.save(flush: true)
            }
        }

    }

    def clientTreeJson(params) {

        def parentId = params.parentId
      
        def clients
        if(!parentId) {
            clients = Client.findAllByParentIdIsNull(params)
        }else{
            clients = Client.findAllByParentId(parentId as Long,params)
        }

        if(!clients || clients.size() == 0) {
            return []
        }
        def cs = clients.collect {client->
            [id: client.id,text: client.name,name: client.name, code:client.code,parentId: client.parentId,parentName:client.clientParentName(), description:client.description,children: clientTreeJson([parentId: client.id])]
        }
        if(!parentId) {
            return cs
        }
        return cs
    }

    def clientTreeJson_1(params) {

        def parentId = params?.parentId

        def clients
        if(!parentId) {
            clients = Client.findAllByParentIdIsNull(params)
        }else{
            clients = Client.findAllByParentId(parentId as Long,params)
        }

        if(!clients || clients.size() == 0) {
            return []
        }
        def cs = clients.collect {client->
            def clientUsers = ClientUser.findAllByClient(client)
            clientUsers = clientUsers.collect {cu->
                [id:cu.id,text: cu.name]
            }
            [id: "@${client.id}",text: client.name,children: clientUsers+clientTreeJson_1([parentId: client.id])]
        }
        if(!parentId) {
            return cs
        }
        return cs
    }
    
    def clientUserTreeJson(Map map) {
        def clientId = map.clientId
        if(!clientId) {
            return [rows: [],total: 0]
        }
        def client = Client.get(clientId as Long)
        if(!client){
            return [rows: [],total: 0]
        }
        def clientUsers
        def count
        if(map.name){
            def query = ClientUser.where {
                client==client && (name==~"%${map.name}%" || code ==~ "%${map.name}%")
            }
            clientUsers = query.list(map)
            count = query.count()
        }else{
            clientUsers = ClientUser.findAllByClient(client,map)
            count = ClientUser.countByClient(client)
        }

        clientUsers = clientUsers.collect {cu->
            def cut = cu.clientUserTypes
            cut = cut.collect {c->
                c.type.name()
            }
            [id: cu.id,text:cu.name,name:cu.name,vip:cu.vip,type:cut,code: cu.code,description: cu.description,'client.id':clientId,clientId:clientId,clientName:client.name]
        }
        return [rows:clientUsers,total:count]
    }

    def areaTreeJson(parentId) {
        def areas
        if(!parentId) {
            areas = Area.findAllByParentIdIsNull()
        }else{
            areas = Area.findAllByParentId(parentId)
        }

        if(!areas || areas.size() == 0) {
            return []
        }
            return areas.collect {area->
            [id: area.id,text: area.name,children: areaTreeJson(area.id)]
        }
    }

    def areaTreeStr(parentId) {
        def areas
        if(!parentId) {
            areas = Area.findAllByParentIdIsNull()
        }else{
            areas = Area.findAllByParentId(parentId)
        }

        if(!areas || areas.size() == 0) {
            return ''
        }
        def result = ''
        areas.each {area->
            result += "<PQ><ID>${area.id}</ID><aa>${area.name}</aa><Remark></Remark>"
            result += areaTreeStr(area.id)
            result += "</PQ>"
        }
        return result
    }

    def clientTreeStr(params) {

        def parentId = params.parentId

        def clients
        def count = 0
        if(!parentId) {
            clients = Client.findAllByParentIdIsNull(params)
        }else{
            clients = Client.findAllByParentId(parentId as Long,params)
        }

        if(!clients || clients.size() == 0) {
            return ''
        }
        def result = ''
        clients.each {client->
            [id: client.id,text: client.name,code:client.code,parentId: client.parentId,parentName:client.clientParentName(), description:client.description,children: clientTreeJson([parentId: client.id])]
            result += "<CustomerC><ID>${client.id}</ID><Caption>${client.name}</Caption><Remark>${client.description}</Remark>"
            result += clientTreeStr([parentId: client.id])
            result += "</CustomerC>"
        }

        return result
    }

    /**
     * 保存角色，并同时更新角色对应的模块和子模块.
     *
     * @param role
     * @param params
     */
    def updateRole(Role role,params) {
        if(!role || !params) {
            throw new RuntimeException()
        }
        def rmIds = params.requestmapId
        if (!springSecurityService.updateRole(role,params)) {
            throw new RuntimeException()
        }
        def rms = role.requestmaps     //已经拥有的模块
        rms.each {rm->
            def id = rm.id
            if (rmIds && rmIds.count("$id")>0) {     //已经拥有id为模块的权限，则不处理
                rmIds = rmIds.findAll{elem->
                    elem != "$id"
                }
            }else{//不在已经拥有模块中，则去掉
                def ca = rm.configAttribute
                def cas = ca.tokenize(',')
                def newcas = cas.findAll {elem->
                    elem != role.authority
                }
                rm.configAttribute = newcas.join(",")
                if(!rm.save(flush: true) ){
                    throw new RuntimeException()
                }
                updateRequestmapChildrenConfigAttribute(rm)
            }
        }
        rmIds.each {id->
            def rem = Requestmap.get(id as Long)
            def ca = rem.configAttribute
            if(ca) {
                ca+=","+role.authority
            }else{
                ca=role.authority
            }
            rem.configAttribute = ca
            if(!rem.save(flush: true)){
                throw new RuntimeException()
            }
            updateRequestmapChildrenConfigAttribute(rem)
        }
        springSecurityService.clearCachedRequestmaps()
    }

    def updateRequestmapChildrenConfigAttribute(Requestmap requestmap) {
        if(!requestmap || !requestmap.id) {
            return
        }
        def children = Requestmap.findAllByParentId(requestmap.id)
        if(!children) {
            return
        }
        children.each {rm->
            rm.configAttribute =  requestmap.configAttribute
            if(!rm.save(flush: true) ){
                throw new RuntimeException()
            }
        }
    }

    void removeDepartment(department) {
        def users = User.findAllByDepartment(department)
        users.each {user->
            user.department = null
            user.save(flush: true)
        }

        def children = Department.findAllByParentId(department.id)
        children.each {depart->
            users = User.findAllByDepartment(depart)
            users.each {user->
                user.department = null
                user.save(flush: true)
            }
            depart.delete(flush: true)
        }

        department.delete(flush: true)
    }

    def formworkCategoryTreeJson(parentId) {
        def formworkCategorys
        if(!parentId) {
            formworkCategorys = FormworkCategory.findAllByParentIdIsNull()
        }else{
            formworkCategorys = FormworkCategory.findAllByParentId(parentId)
        }

        if(!formworkCategorys || formworkCategorys.size() == 0) {
            return []
        }
        return formworkCategorys.collect {formworkCategory->
            [id: formworkCategory.id,text: formworkCategory.name,children: formworkCategoryTreeJson(formworkCategory.id)]
        }
    }
    
    def saveTerminal(Map map) {
        if(!map || !map.terId || !map.area) {
            throw new RuntimeException()
        }
        def terId = map.terId
        def ts = terId.tokenize(',')
        def deviceId = map['device.id'] as Long;
        def device = Device.get(deviceId)
        /*def query = Terminal.where {
            area == map.area && device == device  && terId in ts
        }*/

        //Terminal.executeUpdate("DELETE FROM Terminal where device=:device and terId=:terId",[device:device,terId:terId])

        def terminal
        if(map.id){
            terminal = Terminal.get(map.id as Long);
        }

        if(!terminal) {
            terminal = new Terminal()
        }
       terminal.properties = map;
        if(!terminal.save(flush: true)){
            log.error(terminal.errors)
            throw new RuntimeException(terminal.errors)
        }

        /*ts.each {t->
            def terminal = new Terminal(map)
            terminal.terId = t
            if(!terminal.save(flush: true)){
                throw new RuntimeException(terminal.errors)
            }
        }*/
        return terminal
    }

    def getTerminalXml(def formworkCompositions,Device device){
        def str = ''
        formworkCompositions.each {fc->
            str += "<Area>"
            def hv = ''
            def s1 = ''
            def s2 = ''
            if (fc.category.id == 0){
                hv = "H"
                s1 = "0"
                s2 = '0'
            }
            if (fc.category.id == 1){
                hv = "H"
                s1 = "0"
                s2 = '1'
            }
            if (fc.category.id == 2){
                hv = "H"
                s1 = "1"
                s2 = '0'
            }
            if (fc.category.id == 3){
                hv = "H"
                s1 = "1"
                s2 = '1'
            }
            if (fc.category.id == 4){
                hv = "V"
                s1 = "0"
                s2 = '0'
            }
            if (fc.category.id == 5){
                hv = "V"
                s1 = "0"
                s2 = '1'
            }
            if (fc.category.id == 6){
                hv = "V"
                s1 = "1"
                s2 = '0'
            }
            if (fc.category.id == 7){
                hv = "V"
                s1 = "1"
                s2 = '1'
            }
            def formDetail = fc.formworkDetail
            if(formDetail){
                
                def compositionDetails = CompositionDetails.findByNameAndArea(formDetail.composition,fc.number)
                if(compositionDetails){
                    str += "<Caption>${compositionDetails.area}</Caption>"
                    str += "<Left>${compositionDetails.x}</Left>"
                    str += "<Top>${compositionDetails.y}</Top>"
                    str += "<Width>${compositionDetails.width}</Width>"
                    str += "<Height>${compositionDetails.height}</Height>"
                }
            }
            str += "<HV>${hv}</HV>"
            str += "<Sort1>${s1}</Sort1>"
            str += "<Sort2>${s2}</Sort2>"
            str += "<Count>${fc.quantity}</Count>"
            str += "<Ports>"
            def terminals = Terminal.findAllByDeviceAndArea(device,"a${fc.number}")
            terminals.each {t->
                def ts = t.clientUser?.clientUserTypes
                if(ts){
                    ts = ts.collect {tt->
                        tt.type.id
                    }
                }
                str += "<Port>"
                str += "<ID>${t.id}</ID>"
                str += "<code>${t.number}</code>"
                str += "<letter>${t.letter}</letter>"
                str += "<letterNumber>${t.letterNumber}</letterNumber>"
                str += "<logo>${t.logo?:''}</logo>"
                str += "<status>${t.status?.id?:''}</status>"
                str += "<opening>${t.opening?:''}</opening>"
                str += "<segmentName>${t.segmentName?:''}</segmentName>"
                str += "<opticalNumber>${t.opticalNumber?:''}</opticalNumber>"
                str += "<vip>${t.vip?:''}</vip>"
                str += "<backboneWiring>${t?.backboneWiring?.id?:''}</backboneWiring>"
                str += "<businessType>${ts?ts.join(','):''}</businessType>"
                str += "<splitter>${t.splitter?:''}</splitter>"
                str += "<splitterModel>${t.splitterModel?:''}</splitterModel>"
                str += "<splitRatio>${t.splitRatio?:''}</splitRatio>"
                str += "<opticalSplitterPorts>${t.opticalSplitterPorts?:''}</opticalSplitterPorts>"
                str += "<superiorTerminal>${t.superiorTerminal?:''}</superiorTerminal>"
                str += "<jumperPort>${t.jumperPort?:''}</jumperPort>"
                str += "<description>${t.description?:''}</description>"
                str += "</Port>"
            }
            str += "</Ports>"
            str += "</Area>"
        }
        return str
    }

    /**
     * 网络拓扑，上级
     * 格式： {"ID":"1001","Caption":"A_1","Content":"光交名称：光交1<br>光交编号：abcd-123,<br>端子位置：A-1-B12<br>端子编号：Xde-3223<br>位置：南京光华路",
     "GPS":{"X":"116.399","Y":"39.910"}
     * @param device
     */
    def getNetRouter(Device device,def nets = []){
        def terminal = Terminal.findByDeviceAndBackboneWiring(device,Terminal.BackboneWiring.BACKBONE)
        if (!terminal){
            return nets
        }
        
        def ter = [ID:device.id,Caption:terminal.area,Content:"光交名称：${device.name}<br>光交编号：${device.code},<br>端子位置：${terminal.terId}<br>端子编号：${terminal.code}<br>位置：${device.location?.installation}",GPS:[X:device.location?.longitude,Y:device.location?.latitude]]
        ter = (ter as JSON) as String
        nets << ter
        def parentNode = terminal.superiorTerminal
        if(!parentNode){
            return nets
        }
        def pns = parentNode.tokenize('-')
        def parentDeivceCode = pns[0]
        def device1 = Device.findByCode(parentDeivceCode)
        if(!device1) {
            return nets
        }
        return getNetRouter(device1,nets)
    }
    
    def getDowngetNetRouter(Device device,def nets = []) {
        def terminal = Terminal.findByDeviceAndBackboneWiring(device,Terminal.BackboneWiring.BACKBONE)
        if (!terminal){
            return nets
        }
        def parentCode = "${device.code}-${terminal.terId}"
        def t = Terminal.findBySuperiorTerminal(parentCode)
        if(!t){
            return nets
        }

            def d1 = t.device
            def ter =  [ID:d1.id,Caption:t.area,Content:"光交名称：${d1.name}<br>光交编号：${d1.code},<br>端子位置：${t.terId}<br>端子编号：${t.code}<br>位置：${d1.location?.installation}",GPS:[X:d1.location?.longitude,Y:d1.location?.latitude]]
            ter = (ter as JSON) as String
            nets << ter
            return getDowngetNetRouter(d1,nets)
    }
    /**
     * 获取端子拓扑列表.
     * {"PortID":"1001",PortCode:"232323","PortCaption":"A_1",BoxID:"331",BoxCode:"X341",BoxCaption:"光交11",Address:"南京光华路",Current:0,"GPS":{"X":"116.399","Y":"39.910"}}
     * @param device
     * @param terminal
     */
    def getUpNetRouter(Device device,Terminal terminal,Boolean current) {
        def ter = ["PortID":"${terminal.id}",PortCode:"${terminal.number}","PortCaption":"${terminal.area}",BoxID:"${device.id}",BoxCode:"${device.code}",BoxCaption:"${device.name}",Address:"${device.location?.addr?:''}",Current:"${current?1:0}","GPS":["X":"${device.location?.longitude}","Y":"${device.location?.latitude}"]]
        def parentNode = terminal.superiorTerminal
        if(!parentNode){
            return [(ter as JSON) as String]
        }
        def pns = parentNode.tokenize('-')
        def parentDeivceCode = pns[0]
        def device1 = Device.findByCode(parentDeivceCode)
        if(!device1) {
            return [(ter as JSON) as String]
        }
        def ter1 = Terminal.findByDeviceAndTerId(device1,pns[1])
        return [(ter as JSON) as String] + getUpNetRouter(device1,ter1,false)
    }

    def getDowngetNetRouter(Device device,Terminal terminal){
        def parentCode = "${device.code}-${terminal.terId}"
        def ts = Terminal.findAllBySuperiorTerminal(parentCode)
        if(!ts){
            return []
        }
        def tts = []
        ts.each {t->
            def d = t.device
            def ter = ["PortID":"${t.id}",PortCode:"${t.number}","PortCaption":"${t.area}",BoxID:"${d.id}",BoxCode:"${d.code}",BoxCaption:"${d.name}",Address:"${d.location?.addr?:''}",Current:"0","GPS":["X":"${d.location?.longitude}","Y":"${d.location?.latitude}"]]
            tts += [(ter as JSON) as String]+ getDowngetNetRouter(d,t)
        }
        return tts
    }

    /**
     * 获取端子拓扑列表.
     * {"PortID":"1001",PortCode:"232323","PortCaption":"A_1",BoxID:"331",BoxCode:"X341",BoxCaption:"光交11",Address:"南京光华路",Current:0,"GPS":{"X":"116.399","Y":"39.910"}}
     * @param device
     * @param terminal
     */
    def getUpNetRouter(Terminal terminal,Boolean current) {

        if(!terminal){
            return []
        }

        def ter = ["PortID":"${terminal.id}",PortCode:"${terminal.number}","PortCaption":"${terminal.area}",BoxID:"${terminal.device?.id}",BoxCode:"${terminal.device?.code}",BoxCaption:"${terminal.device?.name}",Address:"${terminal.device?.location?.addr?:''}",Current:"${current?1:0}","GPS":["X":"${terminal.device?.location?.longitude}","Y":"${terminal.device?.location?.latitude}"]]
        def parentNode = terminal.superiorTerminal
        if(!parentNode){
            return [(ter as JSON) as String]
        }

        def ter1 = Terminal.findByNumber(parentNode)
        return  getUpNetRouter(ter1,false) + [(ter as JSON) as String]
    }

    def getDowngetNetRouter(Terminal terminal){

        if(!terminal){
            return []
        }

        def ts = Terminal.findAllBySuperiorTerminal(terminal?.number)
        if(!ts){
            return []
        }
        def tts = []
        ts.each {t->
            def d = t.device
            def ter = ["PortID":"${t.id}",PortCode:"${t.number}","PortCaption":"${t.area}",BoxID:"${d.id}",BoxCode:"${d.code}",BoxCaption:"${d.name}",Address:"${d.location?.addr?:''}",Current:"0","GPS":["X":"${d.location?.longitude}","Y":"${d.location?.latitude}"]]
            tts += [(ter as JSON) as String]+ getDowngetNetRouter(t)
        }
        return tts
    }

    def saveTerminalClientUser(Terminal terminal,ClientUser clientUser){
        if(!TerminalClientUser.create(terminal,clientUser,true)){
            throw new RuntimeException()
        }
        if(clientUser.vip && !terminal.vip) {
            terminal.vip = clientUser.vip
            if(!terminal.save(flush: true)){
                throw new RuntimeException(terminal.errors)
            }
        }

    }

    def removeTerminalClientUser(Terminal terminal,ClientUser clientUser){
        if(!TerminalClientUser.removeAll(terminal,clientUser)  ){
            throw new RuntimeException()
        }
        if(terminal.vip){
            def cus = terminal.clientUsers
            def vip 
            cus.each {
                if(it.vip){
                    vip = it.vip
                    return
                }
            }
            if(!vip){
                terminal.vip = Boolean.FALSE
                if(!terminal.save(flush: true)){
                    throw new RuntimeException(terminal.errors)
                }
            }
        }
    }
}
